
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <strings.h>
#include <signal.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <net/if.h>
#include <sys/ioctl.h>
#include <errno.h>
#include <fcntl.h>

struct fileinfo
{
    char name[50];
    uint32_t size;
};

#define BUFSIZE_MAX 10*1024

int main(int argc, char const *argv[]) // ./a.out IP PORT
{
    
    int sockfd = socket(AF_INET, SOCK_STREAM, 0);

    struct sockaddr_in addr;
    socklen_t len = sizeof(addr);
    addr.sin_family = AF_INET;
    addr.sin_addr.s_addr = inet_addr(argv[1]);
    addr.sin_port = htons(atoi(argv[2]));

    // 发起链接请求
    connect(sockfd,(struct sockaddr *)&addr,len);
    // 选择文件
    struct fileinfo info;
    fgets(info.name, 50, stdin);
    strtok(info.name, "\r\n"); // 直接去除name中的\r\n

    // 发送文件基本属性
    int fd = open(info.name, O_RDONLY);
    if(fd == -1)
    {
        perror("open() failed");
        exit(0);
    }
    info.size = lseek(fd, 0L, SEEK_END);
    lseek(fd, 0L, SEEK_SET);
    printf("文件大小：%d\n", info.size);
    sendto(sockfd, &info, sizeof(info), 0,  (struct sockaddr *)&addr, len);


    // 发送文件内容
    int bufsize = info.size > BUFSIZE_MAX ? BUFSIZE_MAX : info.size; 
    char *buf = calloc(1, bufsize);
    int total = 0;
    while(1)
    {
        int n = read(fd, buf, bufsize);
        if(n > 0)
        {
            int m = send(sockfd, buf, n, 0);
            if(m == -1)
            {
                perror("sendto() failed");
                break;
            }
            total += m;
        }
        else if(n == 0)
            break;
        else if(n == -1)
        {
            perror("read() failed");
            exit(0);
        }
        printf("已发送%d个字节\n", total);
    }

    close(fd);
    close(sockfd);
    free(buf);

    return 0;
}
